#include <stdlib.h>
#include <stdio.h>
#include <pcap/pcap.h>
#include <string.h>
#include <time.h>

#define BUFSIZE 1024
#define RULELEN 128

typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long long u_ll;

// 以太网头
typedef struct ether_header {
    u_char ether_dst[6];
    u_char ether_src[6];
    u_short ether_type;
} EtherHeader;
// IP头
typedef struct ip_header {
    u_char ip_version_headlen;
    u_char ip_serv_type;
    u_short ip_totlen;
    u_short ip_id;
    u_short ip_flag_fragoffset;
    u_char ip_ttl;
    u_char ip_protocol;
    u_short ip_checksum;
    u_int ip_src;
    u_int ip_dst;
} IpHeader;
// tcp header
typedef struct trans_header {
    u_int16_t src_port;
    u_int16_t dst_port;

    u_int32_t seq;
    u_int32_t ack;

    u_int64_t do_not_care;

    u_int32_t option;

} TransHeader;

void resolveTcp(const u_char *tcpData) {
    
    TransHeader *tcpHeader = (TransHeader *)tcpData;

    u_int8_t tcpHeaderLen = (tcpHeader->do_not_care & 0xf000000000000000 >> 60) << 2;
    printf("tcp header len: %d\n", tcpHeaderLen);
    
    if (ntohs(tcpHeader->src_port) == 80 || ntohs(tcpHeader->dst_port) == 80) 
        // http protocol
        printf("data: %s\n", tcpData + tcpHeaderLen);
}

// 处理IP数据报
void resolveIP(const u_char *ipContent) {
    // 提取IP头
    IpHeader *ihead = (IpHeader *)ipContent;
    // 提取传输层协议
    if (ihead->ip_protocol == 6) {
        // tcp protocol
        resolveTcp(ipContent + ((ihead->ip_version_headlen & 0x0f) << 2));
    }
}

// 处理mac帧
void pktHandler(u_char *args, const struct pcap_pkthdr *pktHeader, const u_char *pktContent) {
    // 提取以太网头
    EtherHeader *ehead = (EtherHeader *)pktContent;

    // 查看上层写协议类型，需要进行字节序转换
    if (ntohs(ehead->ether_type) == 0x0800) {
        // ip protocol
        resolveIP(pktContent + 14);
    }
}

int main(int argc, char *argv[]) {

    char errBuf[PCAP_ERRBUF_SIZE];

    // 存放设备
    pcap_if_t* device;
    // 存放网络信息
    bpf_u_int32 netAddr = 0, netMask = 0;
    // 网卡句柄
    pcap_t *pcap_handle;

    // 查找网卡设备
    if(pcap_findalldevs(&device, errBuf) != 0) {
        printf("error: %s\n", errBuf);
        goto cleanup;
    }

    if(device == NULL) {
        printf("no availabel device\n");
        goto cleanup;
    }

    // 网络地址信息
    if(pcap_lookupnet(device->name, &netAddr, &netMask, errBuf) != 0) {
        printf("get net error: %s\n", errBuf);
        goto cleanup;
    }

    // 打开设备
    if((pcap_handle = pcap_open_live(device->name, 65535, 0, 1000, errBuf)) == NULL) {
        printf("pcap open live error: %s\n", errBuf);
        goto cleanup;
    }

    // 循环捕包，每次捕*16个即返回
    if(pcap_loop(pcap_handle, 16, pktHandler, NULL) != 0) {
        printf("loop error: %s\n", errBuf);
        goto cleanup;
    }

    printf("sniffer close\n");
 
 cleanup:
    if (pcap_handle) 
        pcap_close(pcap_handle);
    if (device)
        pcap_freealldevs(device);

    return 0;
}